package site.zhangzhuo.v3;

import java.io.*;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.UUID;

//心
public class Xin implements Serializable {
    @Serial
    private static final long serialVersionUID = 32L;

    //字海
    private final HashMap<Character, Zi> zihai = new HashMap<>();
    //词海
    private final HashMap<String, Ci> cihai = new HashMap<>();
    //文海：UUID，文章开头，特征
    private final HashMap<String,HashMap.SimpleEntry<String,Feature>> wenhai = new HashMap<>();

    //心的大小，字和词的数量
    public int size() {
        return zihai.size()+cihai.size();
    }

    //计算文章特章
    //暂以逗号前后字的统计数据来计算
    public Feature featureOfArticle(Yan yan){
        HashMap<Character,Integer> qian=new HashMap<>();
        HashMap<Character,Integer> hou=new HashMap<>();
        Character c1='^';
        for (Character c : yan.getYanshi().toCharArray()) {
            //上次循环为逗号
            if(c1.equals('，')||c1.equals(',')){
                if(hou.containsKey(c))hou.put(c,hou.get(c)+1);
                else hou.put(c,1);
            }
            //本次循环扫到逗号
            if(c.equals('，')||c.equals(',')){
                if(qian.containsKey(c1))qian.put(c1,qian.get(c1)+1);
                else qian.put(c1,1);
            }
            c1=c;
        }
        Feature rst=new Feature('，',qian,hou);
        return rst;
    }
    //文章是否已经读过
    public boolean hasReaded(Yan yan){
        Feature feat=featureOfArticle(yan);
        for(HashMap.SimpleEntry<String,Feature> entry:wenhai.values()){
            if(feat.likePercent(entry.getValue())>0.7){
                System.out.println("已读过相似文章！");
                System.out.println("开头为："+entry.getKey());
                return true;
            }
        }
        return false;
    }
    //从文章学习字,字之间有顺序关系
    public void learnZiFromArticle(Yan yan) {
        //字数太少不能算文章
        if(yan.getYanshi().length()<200){
            System.out.println("字数太少不算文章！");
            return;
        }
        //如果已读过则不再学习，否则计算特征加入文海
        if(hasReaded(yan)){
            return;
        }
        wenhai.put(UUID.randomUUID().toString(),new AbstractMap.SimpleEntry<>(yan.getYanshi().substring(0,200),featureOfArticle(yan)));
        Zi qian=null,hou=null;
        for (Character c : yan.getYanshi().toCharArray()) {
            //循环中hou永远不会是null
            //qian如果是null表示是开头，统一为'^'字
            hou=zihai.computeIfAbsent(c,k->new Zi(k));
            if(null==qian){
                hou.addQian(new Zi('^'));
            }else{
                hou.addQian(qian);
                qian.addHou(hou);
            }
            qian=hou;
        }
    }
    //从字表学习字,字之间无顺序关系
    public void learnZiFromTable(Yan yan) {
        for (Character c : yan.getYanshi().toCharArray()) {
            zihai.putIfAbsent(c,new Zi(c));
        }
    }
    //从词表学习词,词之间无顺序关系
    public void learnCiFromTable(Yan yan){
        String[] words =yan.getYanshi().split("\\s+");
        for(String str:words) System.out.println(str);
    }

    //从文件反序列化
    public static Xin load(String filename) {
        System.out.println("------reSerialized read Xin---------" + filename);
        try {
            FileInputStream fileIn = new FileInputStream(filename);
            ObjectInputStream in = new ObjectInputStream(fileIn);
            Xin xin = (Xin) in.readObject();
            in.close();
            fileIn.close();
            return xin;
        } catch (IOException i) {
            i.printStackTrace();
        } catch (ClassNotFoundException c) {
            System.out.println("class not found");
            c.printStackTrace();
        }
        return null;
    }

    //序列化到文件
    public void save(String filename) {
        System.out.println("------Serialized save Xin ---------" + filename);
        try {
            FileOutputStream fileOut = new FileOutputStream(filename);
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(this);
            out.close();
            fileOut.close();
        } catch (IOException i) {
            i.printStackTrace();
        }
    }

    //字符串化输出到文件
    public void printToFile(String filename){
        try {
            FileOutputStream fileOut = new FileOutputStream(filename);
            fileOut.write(toString().getBytes());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public String toString(){
        StringBuilder str=new StringBuilder();
        for(Zi z:zihai.values()){
            str.append(z.toString()+"\n");
        }
        return str.toString();
    }
}
